package com.mbuswidget;

import java.util.ArrayList;
import java.util.Collections;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

//import android.provider.UserDictionary.Words;

public class BusRoute implements Comparable<BusRoute> {
	private final Integer id;
	private final String name;
	private final Boolean isLoop;
	private final Integer topOfLoop;
	private final ArrayList<BusStop> stops;
	private Context context;
	private ArrayList<String> duplicates;
	private ArrayList<String> duplicatesBlacklist;

	public BusRoute(BusRoute parent) {
		id = parent.id;
		name = new String(parent.name);
		isLoop = parent.isLoop;
		topOfLoop = parent.topOfLoop;
		context = parent.context;

		stops = new ArrayList<BusStop>();
		for (int i = 0; i < parent.stops.size(); i++) {
			stops.add(new BusStop(parent.stops.get(i)));
		}

		// TODO: Stops should simply just be copied. No need to do
		// generateDuplicates
//		duplicates = parent.duplicates.clone(); 
//		generateDuplicates();
	}

	public BusRoute(Element routeXMLElment, Context context) {
		name = Utils.getTextValue(routeXMLElment, "name");
		id = Integer.parseInt(Utils.getTextValue(routeXMLElment, "id"));
		this.context = context;
		
		String loop = Utils.getTextValue(routeXMLElment, "topofloop");
		if (loop != null) {
			isLoop = true;
			topOfLoop = Integer.parseInt(loop);
		} else {
			isLoop = false;
			topOfLoop = 0;
		}

		stops = new ArrayList<BusStop>();
		NodeList stopsList = routeXMLElment.getElementsByTagName("stop");
		for (int i = 0; i < stopsList.getLength(); i++) {
			Element stop = (Element) stopsList.item(i);
			stops.add(new BusStop(stop));
		}

		duplicates = new ArrayList<String>();
		generateDuplicates();

		// Apply IN/OUT Bound Algorithm...
		applyInOutBound();
	}

	public Integer getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public String getShortName() {
		// TODO: FIX SHORT NAME
		int count = 0;
		String shortName = new String();
		for (String word : name.split("\\s+")) {
			if (word.length() != 0 && Character.isLetter(word.charAt(0))) {
				shortName += Character.toUpperCase(word.charAt(0));
			}
			if (++count > 3) {
				break;
			}
		}
		return shortName;
	}

	public Integer getTopOfLoop() {
		return topOfLoop;
	}

	public ArrayList<BusStop> getStops() {
		return stops;
	}

	public Integer getNumberOfStops() {
		return stops.size();
	}

	public BusStop getStopWithName(String name) {
		for (int i = 0; i < stops.size(); i++) {
			if (stops.get(i).getShortName().compareTo(name) == 0) {
				return stops.get(i);
			}
		}
		return null;
	}

	public void generateDuplicates() {
		ArrayList<String> names = new ArrayList<String>();
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(context);
		duplicates = MBusWidgetConstants.GetDuplicatedRoutes(prefs);
		duplicatesBlacklist = MBusWidgetConstants.GetDuplicatedRoutesBlacklist(prefs);
		int oldSize = duplicates.size();
		for (int x = 0; x < stops.size(); x++) {
			String stopName = stops.get(x).getShortName();

			if (names.indexOf(stopName) != -1) {
				// The Stop is duplicated at least once in this route.

				// Check the global duplicated list. Make sure this stop exists
				// in the list.
				if (duplicates.indexOf(stopName) == -1 && duplicatesBlacklist.indexOf(stopName) == -1) {
					duplicates.add(stopName);
				}
			} else {
				names.add(stopName);
			}
		}
		if (duplicates.size() != oldSize) {
			MBusWidgetConstants.SetDuplicatedRoutes(prefs, duplicates);
		}
	}

	public int findCCLittle() {
		if (stops.size() == 0)
			return -1;

		int closest_stop = 0;
		double minDistance = stops.get(0).getLocation()
				.distanceTo(MBusWidgetConstants.GetCCLittleLoc());

		// Get the exact index of CC_Little
		for (int x = 0; x < stops.size(); x++) {
			BusStop stop = stops.get(x);

			// We found an exact match for CC Little
			if (stop.getShortName().equals(MBusWidgetConstants.CC_LITTLE)) {
				return x;
			}

			// Estimate Distances
			double distance = stop.getLocation().distanceTo(
					MBusWidgetConstants.GetCCLittleLoc());
			if (distance < minDistance) {
				minDistance = distance;
				closest_stop = x;

			}
		}

		// No stop with CC Little name. But here is the closest stop
		return closest_stop;
	}

	public int compareTo(BusRoute another) {
		// TODO Auto-generated method stub
		return name.compareTo(another.getName());
	}

	public void applyInOutBound() {
		// The last stop with the dup name is the In bound. All others are out
		// bound
		// TODO: Create better algorithm that includes CC little, this is to
		// make Pierpoint work for Commuter North/South

		// We know the top of the loop so we can accurately label IN/OUT routes
		int pointOfReference = topOfLoop;
		if (topOfLoop != 0) {
			for (int x = 0; x < stops.size(); x++) {
				String stopName = stops.get(x).getShortName();

				// TODO: Swap this for findCCLittle case, just copy and paste.
				
				// If the stop has a duplicate
				if (duplicates.indexOf(stopName) != -1) {
					if (x < pointOfReference) {
						stops.get(x).setShortName(
								stopName + MBusWidgetConstants.OUT_BOUND_SUFFEX);
					} else {
						stops.get(x).setShortName(
								stopName + MBusWidgetConstants.IN_BOUND_SUFFEX);
					}
				}
			}
		} else {
			pointOfReference = findCCLittle();
			for (int x = 0; x < stops.size(); x++) {
				String stopName = stops.get(x).getShortName();

				// TODO: Swap this for findCCLittle case, just copy and paste.
				
				// If the stop has a duplicate
				if (duplicates.indexOf(stopName) != -1) {
					if (x > pointOfReference) {
						stops.get(x).setShortName(
								stopName + MBusWidgetConstants.OUT_BOUND_SUFFEX);
					} else {
						stops.get(x).setShortName(
								stopName + MBusWidgetConstants.IN_BOUND_SUFFEX);
					}
				}
			}
		}


	}

}
